//! 统一配置加载器
//! 
//! 自动检测配置文件格式并选择合适的解析器

use crate::cluster::ClusterConfig;
use crate::config::config_loader::{ConfigLoader, ConfigFormat, ConfigFormatDetector};
use crate::config::redis_config_parser::RedisConfigParser;
use crate::config::toml_config_parser::TomlConfigParser;
use anyhow::{Result, anyhow};
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use std::sync::Arc;

/// 统一配置加载器
/// 
/// 自动检测配置文件格式并使用相应的解析器
pub struct UnifiedConfigLoader {
    /// 注册的配置解析器
    loaders: HashMap<ConfigFormat, Arc<dyn ConfigLoader>>,
}

impl UnifiedConfigLoader {
    /// 创建新的统一配置加载器
    pub fn new() -> Self {
        let mut loaders: HashMap<ConfigFormat, Arc<dyn ConfigLoader>> = HashMap::new();
        
        // 注册内置解析器
        loaders.insert(ConfigFormat::RedisConf, Arc::new(RedisConfigParser));
        loaders.insert(ConfigFormat::Toml, Arc::new(TomlConfigParser));
        
        Self { loaders }
    }
    
    /// 注册自定义配置解析器
    pub fn register_loader(&mut self, format: ConfigFormat, loader: Arc<dyn ConfigLoader>) {
        self.loaders.insert(format, loader);
    }
    
    /// 从文件加载配置（自动检测格式）
    pub fn load_from_file<P: AsRef<Path>>(&self, path: P) -> Result<ClusterConfig> {
        let path = path.as_ref();
        
        // 首先尝试根据文件扩展名检测格式
        if let Some(format) = ConfigFormatDetector::detect_by_extension(path) {
            if let Some(loader) = self.loaders.get(&format) {
                return loader.load_from_file(path);
            }
        }
        
        // 如果扩展名检测失败，读取内容进行检测
        let content = fs::read_to_string(path)
            .map_err(|e| anyhow!("读取配置文件失败: {}", e))?;
        
        self.load_from_string(&content)
    }
    
    /// 从字符串内容加载配置（自动检测格式）
    pub fn load_from_string(&self, content: &str) -> Result<ClusterConfig> {
        // 先检查是否是Redis .conf格式
        if let Some(redis_loader) = self.loaders.get(&ConfigFormat::RedisConf) {
            if redis_loader.validate_format(content) {
                match redis_loader.load_from_string(content) {
                    Ok(config) => {
                        tracing::info!("使用 Redis Conf 格式解析器成功加载配置");
                        return Ok(config);
                    }
                    Err(e) => {
                        tracing::warn!("Redis Conf格式解析器加载失败: {}", e);
                    }
                }
            }
        }
        
        // 再尝试其他格式
        for (format, loader) in &self.loaders {
            if *format == ConfigFormat::RedisConf {
                continue; // 已经检查过了
            }
            
            if loader.validate_format(content) {
                match loader.load_from_string(content) {
                    Ok(config) => {
                        tracing::info!("使用 {} 格式解析器成功加载配置", format.name());
                        return Ok(config);
                    }
                    Err(e) => {
                        tracing::warn!("{}格式解析器加载失败: {}", format.name(), e);
                        continue;
                    }
                }
            }
        }
        
        Err(anyhow!("无法识别配置文件格式或所有解析器都失败"))
    }
    
    /// 指定格式加载配置
    pub fn load_with_format<P: AsRef<Path>>(&self, path: P, format: ConfigFormat) -> Result<ClusterConfig> {
        let loader = self.loaders.get(&format)
            .ok_or_else(|| anyhow!("不支持的配置格式: {}", format.name()))?;
        
        loader.load_from_file(path.as_ref())
    }
    
    /// 获取支持的格式列表
    pub fn supported_formats(&self) -> Vec<ConfigFormat> {
        self.loaders.keys().copied().collect()
    }
    
    /// 获取格式的加载器信息
    pub fn get_loader_info(&self, format: ConfigFormat) -> Option<String> {
        self.loaders.get(&format).map(|loader| {
            format!("{} - 支持扩展名: {:?}", 
                loader.loader_name(), 
                loader.supported_extensions())
        })
    }
}

impl Default for UnifiedConfigLoader {
    fn default() -> Self {
        Self::new()
    }
}

/// 便捷的配置加载函数
/// 
/// 自动检测格式并加载配置文件
pub fn load_config<P: AsRef<Path>>(path: P) -> Result<ClusterConfig> {
    let loader = UnifiedConfigLoader::new();
    loader.load_from_file(path)
}

/// 从字符串加载配置的便捷函数
pub fn load_config_from_string(content: &str) -> Result<ClusterConfig> {
    let loader = UnifiedConfigLoader::new();
    loader.load_from_string(content)
}

